package com.illtamer.infinite.sillage.annotation.handler;

import com.illtamer.infinite.sillage.annotation.Convert;
import com.illtamer.infinite.sillage.annotation.SecurityUser;
import com.illtamer.infinite.sillage.config.exception.ConvertNotSupportException;
import com.illtamer.infinite.sillage.pojo.*;
import org.springframework.core.MethodParameter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 实体类参数转换处理类
 * */
@Component
public class ConvertHandler implements HandlerMethodArgumentResolver {

    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(Convert.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        final Class<?> type = parameter.getParameterType();
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        Assert.notNull(request);
        if (type == Blog.class) {
            Blog blog = new Blog();

            blog.setId(getInteger("id", request));
            blog.setTitle(request.getParameter("title"));
            blog.setCover(request.getParameter("cover"));
            blog.setSummary(request.getParameter("summary"));
            blog.setContent(request.getParameter("content"));
            blog.setFlag(getInteger("flag", request));

            blog.setRecommend(getBoolean("recommend", request));
            blog.setAppreciation(getBoolean("reward", request));
            blog.setShareStatement(getBoolean("transfer", request));
            blog.setCommentable(getBoolean("comment", request));
            blog.setTags(getTags(request));
            blog.setType(getType(request));

            blog.setPublished(getBoolean("published", false, request));
//            blog.setViews(getInteger("views", 0, request));
//            blog.setCreateTime(blog.getId() == null ? date : FORMAT.parse(request.getParameter("createTime")));
            blog.setUpdateTime(new Date());
            if (blog.getId() == null) {
                blog.setViews(0);
                blog.setCreateTime(new Date());
            }

            return blog;
        } else if (type == Comment.class) {
            Comment comment = new Comment();

            comment.setBlog(new Blog(getInteger("blogId", request)));
            comment.setParentComment(new Comment(getInteger("parentCommentId", request)));
            comment.setNick(request.getParameter("nick"));
            comment.setEmail(request.getParameter("email"));
            comment.setContent(request.getParameter("content"));
            comment.setAvatar("https://img0.baidu.com/it/u=1431430332,1380391605&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=400");
            comment.setCreateTime(new Date());
            return comment;
        }
        throw new ConvertNotSupportException();
    }

    @SuppressWarnings("all")
    private static Integer getInteger(String key, Integer value, HttpServletRequest request) {
        final Integer cache = getInteger(key, request);
        return cache == null ? value : cache;
    }

    @SuppressWarnings("all")
    private static Boolean getBoolean(String key, Boolean value, HttpServletRequest request) {
        final Boolean cache = getBoolean(key, request);
        return cache == null ? value : cache;
    }

    private static Integer getInteger(String key, HttpServletRequest request) {
        final String param = request.getParameter(key);
        return param != null && param.length() > 0 ? Integer.parseInt(param) : null;
    }

    private static Boolean getBoolean(String key, HttpServletRequest request) {
        final String param = request.getParameter(key);
        return param != null && param.length() > 0 ? Boolean.parseBoolean(param) : null;
    }

    private static Type getType(HttpServletRequest request) {
        final String param = request.getParameter("typeId");
        if (param == null || param.length() == 0) return null;
        return new Type(Integer.parseInt(param));
    }

    private static List<Tag> getTags(HttpServletRequest request) {
        final String[] params = request.getParameterValues("tagId[]");
        if (params == null || params.length == 0) return null;
        return Arrays.stream(params).map(param -> new Tag(Integer.parseInt(param))).collect(Collectors.toList());
    }

}
